-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add FreeBSD Arm64 support #295
Conversation
420d9fc
to
fddcfaf
Compare
src/impl_aarch64_freebsd.c
Outdated
// TODO: Add sveebf16 detection | ||
ID_AA64ZFR0_FEATURES(sveebf16, AARCH64_SVEBF16) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/impl_aarch64_freebsd.c
Outdated
// TODO: Add ssbs2 detection | ||
ID_AA64PFR1_FEATURES(ssbs2, AARCH64_SSBS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Speculative Store Bypassing controls in AArch64 state. Defined values are:
SSBS | Meaning |
---|---|
0b0000 | AArch64 provides no mechanism to control the use of Speculative Store Bypassing. |
0b0001 | AArch64 provides the PSTATE.SSBS mechanism to mark regions that are Speculative Store Bypass Safe. |
0b0010 | AArch64 provides the PSTATE.SSBS mechanism to mark regions that are Speculative Store Bypassing Safe, and the MSR and MRS instructions to directly read and write the PSTATE.SSBS field. |
FEAT_SSBS
implements the functionality identified by the value 0b0001.
FEAT_SSBS2
implements the functionality identified by the value 0b0010.
in current impl linux identifies ssbs2 as ssbs:
HWCAP_SSBS
Functionality implied by ID_AA64PFR1_EL1.SSBS == 0b0010.
refs:
- https://developer.arm.com/documentation/ddi0601/2020-12/AArch64-Registers/ID-AA64PFR1-EL1--AArch64-Processor-Feature-Register-1
- https://docs.kernel.org/arm64/elf_hwcaps.html
so we should add ssbs2
new field, set to true ssbs
for linux when ID_AA64PFR1_EL1.SSBS == 0b0010 is true, for freebsd just add here new AARCH64_SSBS2
src/impl_aarch64_freebsd.c
Outdated
ID_AA64ISAR1_SET_FEATURE(api_pac, "API PAC"), | ||
ID_AA64ISAR1_SET_FEATURE(api_epac, "API EPAC"), | ||
ID_AA64ISAR1_SET_FEATURE(api_epac2, "Impl PAuth+EPAC2"), | ||
ID_AA64ISAR1_SET_FEATURE(api_fpac, "Impl PAuth+FPAC"), | ||
ID_AA64ISAR1_SET_FEATURE(api_fpac_combined, "Impl PAuth+FPAC+Combined"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
linux HWCAP idenifies only 0b0001 cases:
HWCAP_PACA
Functionality implied by ID_AA64ISAR1_EL1.APA == 0b0001 or ID_AA64ISAR1_EL1.API == 0b0001, as described by Pointer authentication in AArch64 Linux.
HWCAP_PACG
Functionality implied by ID_AA64ISAR1_EL1.GPA == 0b0001 or ID_AA64ISAR1_EL1.GPI == 0b0001, as described by Pointer authentication in AArch64 Linux.
we can add new fields and detect it in Linux as well via check HWCAP_CPUID, if this value is true, we can get EL1 info in userland, for example, pacg get info via inline asm
refs:
Thx a lot for the great PR ! That's quite some work 😄 I especially like the detailed sources. AFAIU most of the code is inspired from https://github.com/freebsd/freebsd-src/tree/main/sys/arm64/arm64. A few questions though:
|
correct, we can read privilegied
it's worth noting that All raspberry pi versions supports from 12.0.0: So, we can move arm64 logic to separate file like x86 and get cpu info via assembly and reuse the same code for Advantages:
Disadvantages:
About parsing |
Highly appreciate the thorough documentation (as always). I would be tempted to land this patch first and work on a refactoring as a second step. WDYT? |
On FreeBSD you need to use |
@pkubaj, I didn't know about this function, thanks. However, this function since 12.0.0 (https://man.freebsd.org/cgi/man.cgi?query=elf_aux_info&sektion=3&format=html) as well as reading system registers from userland. @gchatelet, what do you think? |
Looking at FreeBSD history; 12.0.0 is available from early 2019. It's quite recent. We'll probably have to go the linux way and get data from @pkubaj do you know what was the official way to get cpu features in userland for FreeBSD pre 12.0.0? |
I wouldn't call it recent. FreeBSD 12.3-RELEASE is the oldest version currently supported. FreeBSD 12 as a whole goes EOL this year. That said, the recommended way for older versions was something like: unsigned long hwcaps2 = 0;
size_t len = sizeof(hwcaps2);
sysctlbyname("hw.cpu_features2", &hwcaps2, &len, NULL, 0); That was for |
@pkubaj, @gchatelet, I checked sysctlbyname I just leave here part of hw.machine: arm64
hw.model: ARM Cortex-A72 r0p3
hw.ncpu: 4
hw.byteorder: 1234
hw.physmem: 8420352000
hw.usermem: 7730343936
hw.pagesize: 4096
hw.machine_arch: aarch64
hw.realmem: 8443125760
hw.cpufreq.temperature: 35499
hw.cpufreq.voltage_sdram_p: 1100000
hw.cpufreq.voltage_sdram_i: 1100000
hw.cpufreq.voltage_sdram_c: 1100000
hw.cpufreq.voltage_core: 850000
hw.cpufreq.turbo: 0
hw.cpufreq.sdram_freq: 400000000
hw.cpufreq.core_freq: 200000000
hw.cpufreq.arm_freq: 600000000 Looks like so, I think we worth to use proposed @gchatelet approach, if no objections, but I have to update current impl as https://github.com/freebsd/freebsd-src/blob/stable/11/sys/arm64/arm64/identcpu.c#L717-L724 Other fields that HWCAP does not provide, we can use with ID_AA64_* EL1 from 12.0.0 version for FreeBSD and Linux. what do you think? |
Ok let's go with |
04dd437
to
58478d4
Compare
@gchatelet, I have question related to fallback, I checked the first supported version of Arm64 and it is 11 version and this version is Tier 2 (Developmental and Niche Architectures), since 13 version Arm64 is Tier 1 (Fully-Supported Architectures). What do you think to use only also, 11-STABLE is EOL refs: |
@toor1245 SGTM let's drop support for 11 and go with 12. Thx! |
Getting all the features is handled by reading /var/run/dmesg.boot. Feature detections were taken from the freebsd kernel code sys/arm64/arm64/identcpu.c
41fb37a
to
e454ffe
Compare
545b2f2
to
c94a331
Compare
afe7840
to
6408bda
Compare
fix clang format for |
9d6f18a
to
699bb0c
Compare
cc6242c
to
7fc1bfd
Compare
7fc1bfd
to
a21ff2c
Compare
@gchatelet, @Mizux, this PR is ready to review. Few notes that you should know 1) The root shell is tcsh(1) by default on FreeBSD 13 and earlier and sh(1) on FreeBSD 14 and later. So for Bazel user can get the following message if try to run without bash mhohsadze@generic:~/cpu_features_toor1245_2 $ bazel run list_cpu_features
INFO: Analyzed target //:list_cpu_features (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:list_cpu_features up-to-date:
bazel-bin/list_cpu_features
INFO: Elapsed time: 0.735s, Critical Path: 0.02s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/list_cpu_features
FATAL: execv of '/usr/local/bin/bash' failed: (error: 2): No such file or directory To fix this issue I installed pkg bash pkg install bash mhohsadze@generic:~/cpu_features_toor1245_2 $ bazel run list_cpu_features
INFO: Analyzed target //:list_cpu_features (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:list_cpu_features up-to-date:
bazel-bin/list_cpu_features
INFO: Elapsed time: 0.991s, Critical Path: 0.02s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/list_cpu_features
arch : aarch64
implementer : 0 (0x00)
variant : 0 (0x00)
part : 0 (0x00)
revision : 0 (0x00)
flags : asimd,crc32,fp ref: https://docs.freebsd.org/en/articles/linux-users/#shells 2) It looks like googletest with Bazel doesn't work on FreeBSD, there is known issue that Bazel use clang instead of clang++ bazelbuild/bazel#12023 I got the following error message: mhohsadze@generic:~/cpu_features_toor1245_2 $ bazel run cpuinfo_test
DEBUG: Rule 'com_google_googletest' indicated that a canonical reproducible form can be obtained by modifying arguments commit = "e2239ee6043f73722e7aa812a459f54a28552929" and dropping ["tag"]
DEBUG: Repository com_google_googletest instantiated at:
/home/mhohsadze/cpu_features_toor1245_2/WORKSPACE:5:15: in <toplevel>
Repository rule git_repository defined at:
/home/mhohsadze/.cache/bazel/_bazel_mhohsadze/c0c856c8d68586bbc248a05faeb84cd1/external/bazel_tools/tools/build_defs/repo/git.bzl:181:33: in <toplevel>
INFO: Analyzed target //:cpuinfo_test (2 packages loaded, 174 targets configured).
INFO: Found 1 target...
INFO: From Compiling test/cpuinfo_aarch64_test.cc:
test/cpuinfo_aarch64_test.cc:77:24: warning: unused function 'cpu' [-Wunused-function]
static FakeCpuAarch64& cpu() {
^
1 warning generated.
ERROR: /home/mhohsadze/cpu_features_toor1245_2/BUILD.bazel:343:8: Linking cpuinfo_test failed: (Exit 1): clang failed: error executing command (from target //:cpuinfo_test) /usr/bin/clang -o bazel-out/freebsd-fastbuild/bin/cpuinfo_test -Xlinker -rpath -Xlinker '$ORIGIN/_solib_freebsd/' -Xlinker -rpath -Xlinker ... (remaining 15 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
ld: error: bazel-out/freebsd-fastbuild/bin/_solib_freebsd/libexternal_Scom_Ugoogle_Ugoogletest_Slibgtest.so: undefined reference to nextafter [--no-allow-shlib-undefined]
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Target //:cpuinfo_test failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 108.718s, Critical Path: 58.37s
INFO: 44 processes: 11 internal, 33 processwrapper-sandbox.
FAILED: Build did NOT complete successfully
ERROR: Build failed. Not running target 3) I noticed a strange thing that I can read system registers like MIDR_EL1 in user mode but elf_aux_info #include <sys/auxv.h>
#include <stdio.h>
#include <stdint.h>
static uint64_t
extract_bit_range(uint64_t reg, uint64_t msb, uint64_t lsb)
{
const uint64_t bits = msb - lsb + 1ULL;
const uint64_t mask = (1ULL << bits) - 1ULL;
return ((reg >> lsb) & mask);
}
uint64_t
get_midr_el1()
{
uint64_t midr_el1;
__asm("mrs %0, MIDR_EL1" : "=r"(midr_el1));
return midr_el1;
}
int
main()
{
unsigned long hwcaps;
uint64_t midr_el1;
elf_aux_info(AT_HWCAP, &hwcaps, sizeof(unsigned long));
printf("hwcap_cpuid: %lu\n", hwcaps & HWCAP_CPUID);
midr_el1 = get_midr_el1();
printf("midr_el1: 0x%lx\n", midr_el1);
printf("implementer: 0x%lx\n", extract_bit_range(midr_el1, 31, 24));
printf("variant: 0x%lx\n", extract_bit_range(midr_el1, 23, 20));
printf("part: 0x%lx\n", extract_bit_range(midr_el1, 15, 4));
printf("revision: 0x%lx\n", extract_bit_range(midr_el1, 3, 0));
return 0;
} Output: hwcap_cpuid: 0
midr_el1: 0x410fd083
implementer: 0x41
variant: 0x0
part: 0xd08
revision: 0x3 I checked identcpu.c and I did not find the location of HWCAP_CPUID where the value of that's why it reports values as 0, since info.features.cpuid = 0. Aarch64Info GetAarch64Info(void) {
// ...
if (info.features.cpuid) {
const uint64_t midr_el1 = GetMidrEl1();
info.implementer = (int)ExtractBitRange(midr_el1, 31, 24);
info.variant = (int)ExtractBitRange(midr_el1, 23, 20);
info.part = (int)ExtractBitRange(midr_el1, 15, 4);
info.revision = (int)ExtractBitRange(midr_el1, 3, 0);
}
return info;
} So I wrote to one of the FreeBSD Arm64 committers to confirm this issue.
|
@gchatelet, @Mizux, It would also be great to add Bazel instructions and known issues to README as separate patch. |
Thx for the PR @toor1245, I'll look it up today. |
|
||
PLATFORM_OS_ANDROID = ("@platforms//os:android") | ||
|
||
PLATFORM_OS_FREEBSD = ("@platforms//os:freebsd") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this may look weird that we have to provide this file and not use @platforms//...
directly but this comes from the fact that we have internal definitions for these cpu/platforms that are different from upstream Bazel. I hope we'll be able to remove this technical debt one day.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the tests will have to be split at some point. It's starting to be too complicated. Not in this PR but definitely in the near future.
Thx again for the hard work here. Let's merge and iterate if needed before the next release. |
@gchatelet, I got confirmation that it was a bug, it was fixed couple days ago, see |
I did build with the latest changes from main branch and can confirm that it works fine! mhohsadze@generic:~/cpu_features_toor1245_2 $ bazel run list_cpu_features
Starting local Bazel server and connecting to it...
... still trying to connect to local Bazel server (1532) after 10 seconds ...
INFO: Analyzed target //:list_cpu_features (37 packages loaded, 192 targets configured).
INFO: Found 1 target...
Target //:list_cpu_features up-to-date:
bazel-bin/list_cpu_features
INFO: Elapsed time: 61.431s, Critical Path: 4.52s
INFO: 8 processes: 1 internal, 7 processwrapper-sandbox.
INFO: Build completed successfully, 8 total actions
INFO: Running command line: bazel-bin/list_cpu_features
arch : aarch64
implementer : 65 (0x41)
variant : 0 (0x00)
part : 3336 (0xD08)
revision : 3 (0x03)
flags : asimd,cpuid,crc32,fp
mhohsadze@generic:~/cpu_features_toor1245_2 $ So, just to note that it works for now only in main branch A user with a stable version of FreeBSD will see the result I posted recently: mhohsadze@generic:~/cpu_features_toor1245_2 $ bazel run list_cpu_features
INFO: Analyzed target //:list_cpu_features (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:list_cpu_features up-to-date:
bazel-bin/list_cpu_features
INFO: Elapsed time: 0.991s, Critical Path: 0.02s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/list_cpu_features
arch : aarch64
implementer : 0 (0x00)
variant : 0 (0x00)
part : 0 (0x00)
revision : 0 (0x00)
flags : asimd,crc32,fp |
Thx a lot for taking the time to contact the team and report here. |
@gchatelet, yes I agree with you that we should create an issue |
@gchatelet, I added issue #344 |
Thx a lot @toor1245 🙏 , I meant to do it but I've been busy. |
Getting all the features is handled by reading /var/run/dmesg.boot. Feature detections were taken from the freebsd kernel code sys/arm64/arm64/identcpu.c. This PR does not contain MIDR_EL1 and cache function definitions. For future detection midr we can try to use mapping of CPU 0 string to MIDR_EL1 values: https://github.com/freebsd/freebsd-src/blob/main/sys/arm64/arm64/identcpu.c#L173, but not in this PR since the changes are so big
refs to review:
https://github.com/freebsd/freebsd-src/tree/main/sys/arm64/arm64